﻿using Wizard.Compiler.Parsers;
using System;

namespace Wizard.Compiler.Tokenizers
{
    using Wizard.Runtime;

    internal class BasicTokenizer : BaseTokenizer
    {
        internal BasicTokenizer(SourcePos sourcePos)
            : base(sourcePos)
        {
        }

        protected internal override int GetPriority(IHasValue ValueLeft, TokenType tt)
        {
            switch (tt)
            {
                case TokenType.operator_plus:
                case TokenType.operator_minus:
                    return (int)eVbPriority.plusminus;

                case TokenType.operator_concat:
                    return (int)eVbPriority.concat;

                case TokenType.operator_mul:
                case TokenType.operator_div:
                    return (int)eVbPriority.muldiv;

                case TokenType.operator_percent:
                    return (int)eVbPriority.percent;

                case TokenType.operator_or:
                    return (int)eVbPriority.or;

                case TokenType.operator_and:
                    return (int)eVbPriority.and;

                case TokenType.operator_ne:
                case TokenType.operator_gt:
                case TokenType.operator_ge:
                case TokenType.operator_eq:
                case TokenType.operator_le:
                case TokenType.operator_lt:
                    return (int)eVbPriority.equality;
                default:
                    // we don't want to crash as we might have a closing parenthesis
                    // or something else parsed by the caller
                    return (int)eVbPriority.none;
            }
        }

        protected internal override int GetUnaryPriority(TokenType type)
        {
            switch (type)
            {
                case TokenType.operator_not:
                    return (int)eVbPriority.not;
                case TokenType.operator_minus:
                    return (int)eVbPriority.unaryminus;
                default:
                    throw new Exception("Unknown unary operator");
            }
        }

        protected override TokenType GetInvalidIdentifiers(string word, string lowerCaseWord)
        {
            switch (lowerCaseWord)
            {
                case "and":
                    return TokenType.operator_and;
                case "or":
                    return TokenType.operator_or;
                case "not":
                    return TokenType.operator_not;
                case "yes":
                    return TokenType.value_true;
                case "no":
                    return TokenType.value_false;
            }
            return base.GetInvalidIdentifiers(word, lowerCaseWord);
        }

        private enum eVbPriority
        {
            none = 0,
            question_mark = 1,
            or = 2,
            and = 3,
            not = 4,
            equality = 5,
            concat = 6,
            plusminus = 7,
            muldiv = 8,
            percent = 9,
            unaryminus = 10
        }

    }
}